package interpreter;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map.Entry;

import client.Measurement;
import client.ProcessingMeasurement;
import client.ResponseMeasurement;
import client.ThinkMeasurement;
import config.Config;

public class SingleExperimentInterpreter {
	public static final int SKIP_MARGINS = 1;
	
	
	public static RealResult DoFile(int []params,String infilename, String outfilename) {
		long interpreter_step = Config.interpreter_step;
		// ADDED TO CHANGE THE INTERPRETER STEP TO 60 SECONDS FOR 0.01 DATABASES
		if(params[2] == 1) {
			// SCALING FACTOR OF 0.01
			interpreter_step = 60 * 1000;
			System.out.println("FOR FILENAME " + infilename + " I will use 60 seconds as time step.");
		} else {
			interpreter_step = 200 * 1000;
			System.out.println("FOR FILENAME " + infilename + " I will use 200 seconds as time step.");
		}
		// DONE
		
		
		ArrayList<Measurement> results = new ArrayList<Measurement>();
		long smallest_stop = Long.MAX_VALUE;
		long largest_stop = Long.MIN_VALUE;
		try {
			//use buffering, reading one line at a time
			//FileReader always assumes default encoding is OK!
			BufferedReader input =  new BufferedReader(new FileReader(infilename));
			try {
				String line = null; //not declared within while loop
				/*
				* readLine is a bit quirky :
				* it returns the content of a line MINUS the newline.
				* it returns null only for the END of the stream.
				* it returns an empty String if two newlines appear in a row.
				*/
				while (( line = input.readLine()) != null) {
					if(line.isEmpty()) {
						continue;
					}
					if(line.startsWith("RESPONSE: ")) {
						line = line.substring(10);
						String []pieces = line.split(",");
						int clientID = Integer.parseInt(pieces[0]);
						String q = pieces[1];
						long start = Long.parseLong(pieces[2]);
						long stop = Long.parseLong(pieces[3]);
						if(stop < smallest_stop) {
							smallest_stop = stop;
						}
						if(stop > largest_stop) {
							largest_stop = stop;
						}
						boolean success = pieces[4].equals("success") ? true : false;
						results.add(new ResponseMeasurement(clientID, start, stop, q, success));
					} else if(line.startsWith("THINK: ")) {
						line = line.substring(7);
						String []pieces = line.split(",");
						int clientID = Integer.parseInt(pieces[0]);
						long start = Long.parseLong(pieces[1]);
						long stop = Long.parseLong(pieces[2]);
						if(stop < smallest_stop) {
							smallest_stop = stop;
						}
						if(stop > largest_stop) {
							largest_stop = stop;
						}
						results.add(new ThinkMeasurement(clientID, start, stop));
					} else if (line.startsWith("PROCESSING: ")) {
						line = line.substring("PROCESSING: ".length());
						String []pieces = line.split(",");
						int clientID = Integer.parseInt(pieces[0]);
						String server = pieces[1];
						String query = pieces[2];
						long start = Long.parseLong(pieces[3]);
						long stop = Long.parseLong(pieces[4]);
						boolean success = pieces[5].equals("success");
						results.add(new ProcessingMeasurement(clientID, start, stop, server, query, success));
					}
				}
			} finally {
				input.close();
			}
		} catch (IOException ex){
			ex.printStackTrace();
		}
		
		long total_time = largest_stop - smallest_stop;
		int steps = (int)(((double)total_time) / ((double)interpreter_step) + 0.5);
		
		long executed_before = smallest_stop + interpreter_step;
		int current_result = 0;
		
		double []T = new double[steps];
		double []ART = new double[steps];
		double []MRT = new double[steps];
		double []ATT = new double[steps];
		double []MTT = new double[steps];
		Task2and3Data task2Data = new Task2and3Data(interpreter_step, steps);
		HashMap<String, Task2and3Data> task3Servers = new HashMap<String, Task2and3Data>();
		
		for(int i=0; i<steps; i++) {
			ArrayList<ResponseMeasurement> considered_response_results = new ArrayList<ResponseMeasurement>();
			ArrayList<ThinkMeasurement> considered_think_results = new ArrayList<ThinkMeasurement>();
			ArrayList<Measurement> proc_time_client = new ArrayList<Measurement>();
			ArrayList<Measurement> proc_time_server = new ArrayList<Measurement>();
			HashMap<String, ArrayList<Measurement>> splitting = new HashMap<String, ArrayList<Measurement>>();
			
			while(current_result < results.size() && 
					results.get(current_result).getStop() <= executed_before) {
				if (results.get(current_result) instanceof ResponseMeasurement) {
					considered_response_results.add((ResponseMeasurement)results.get(current_result));
					proc_time_client.add(results.get(current_result));
				} else if (results.get(current_result) instanceof ThinkMeasurement) {
					considered_think_results.add((ThinkMeasurement)results.get(current_result));
				} else if (results.get(current_result) instanceof ProcessingMeasurement) {
					ProcessingMeasurement pm = (ProcessingMeasurement) results.get(current_result);
					proc_time_server.add(pm);
					if (!splitting.containsKey(pm.host)) {
						splitting.put(pm.host, new ArrayList<Measurement>());
					}
					if (!task3Servers.containsKey(pm.host)) {
						task3Servers.put(pm.host, new Task2and3Data(interpreter_step, steps));
					}
					splitting.get(pm.host).add(pm);
				}
				current_result ++;
			}
			
			T[i] = ComputeThroughput(considered_response_results, interpreter_step);
			ART[i] = ComputeAverageResponseTime(considered_response_results);
			MRT[i] = ComputeMedianResponseTime(considered_response_results);
			ATT[i] = ComputeAverageThinkTime(considered_think_results);
			MTT[i] = ComputeMedianThinkTime(considered_think_results);
			for (Entry<String, Task2and3Data> e : task3Servers.entrySet()) {
				ArrayList<Measurement> m = splitting.get(e.getKey());
				if (m == null) {
					m = new ArrayList<Measurement>();
					splitting.put(e.getKey(), m);
				}
				ComputeDataTask2Parameter t = new ComputeDataTask2Parameter(task2Data, executed_before, i, m);
				t.computeDataTask2();
				t.computeIndividualServer(e.getKey());
			}
			ComputeDataTask2Parameter t1 = new ComputeDataTask2Parameter(task2Data, executed_before, i, proc_time_client);
			t1.computeDataTask2();
			executed_before += interpreter_step;
		}
		task2Data.computeUtilization();
		task2Data.computeMeanArrivalTime();
		try {
			FileWriter fstream = new FileWriter(outfilename, false);
			BufferedWriter outFile = new BufferedWriter(fstream);
			
			long start_timestamp = smallest_stop;
			long stop_timestamp;
			
			for(int i=0; i<steps; i++) {
				String line = "";
				line += (long)(start_timestamp / 1000.0);
				line += ",";
				stop_timestamp = start_timestamp + interpreter_step;
				if(stop_timestamp > largest_stop) {
					stop_timestamp = largest_stop;
				}
				line += (long)(stop_timestamp / 1000.0);
				line += ",";
				line += (long)((stop_timestamp - smallest_stop) / 1000.0);
				line += "," + T[i] + "," + ART[i] + "," + MRT[i];
				outFile.write(line);
				outFile.newLine();
				
				start_timestamp += interpreter_step;
			}
			
			outFile.close();
		} catch (Exception e) {
			System.out.println("Can't write to experiment file!!!");
			e.printStackTrace();
		}
		
		
		
		// Compute means & deviations
		RealResult r = new RealResult();
		
		r.params = params.clone();
		r.N = steps - SKIP_MARGINS - SKIP_MARGINS;
		
		r.Tmean = ComputeMean(T, SKIP_MARGINS);
		r.TstdDev = ComputeStdDev(T, r.Tmean, SKIP_MARGINS);
		
		r.ARTmean = ComputeMean(ART, SKIP_MARGINS);
		r.ARTstdDev = ComputeStdDev(ART, r.ARTmean, SKIP_MARGINS);
		
		r.MRTmean = ComputeMean(MRT, SKIP_MARGINS);
		r.MRTstdDev = ComputeStdDev(MRT, r.MRTmean, SKIP_MARGINS);
		
		
		
		r.confidence1percent = 80;
		r.confidence2percent = 90;
		
		int conf1_index = 0;
		int conf2_index = 1;
		
		r.confidence1Tmin = getLowerConfidenceInterval(conf1_index, r.Tmean, r.TstdDev, r.N);
		r.confidence1Tmax = getUpperConfidenceInterval(conf1_index, r.Tmean, r.TstdDev, r.N);
		r.confidence2Tmin = getLowerConfidenceInterval(conf2_index, r.Tmean, r.TstdDev, r.N);
		r.confidence2Tmax = getUpperConfidenceInterval(conf2_index, r.Tmean, r.TstdDev, r.N);
		
		
		r.confidence1ARTmin = getLowerConfidenceInterval(conf1_index, r.ARTmean, r.ARTstdDev, r.N);
		r.confidence1ARTmax = getUpperConfidenceInterval(conf1_index, r.ARTmean, r.ARTstdDev, r.N);
		r.confidence2ARTmin = getLowerConfidenceInterval(conf2_index, r.ARTmean, r.ARTstdDev, r.N);
		r.confidence2ARTmax = getUpperConfidenceInterval(conf2_index, r.ARTmean, r.ARTstdDev, r.N);
		
		
		r.confidence1MRTmin = getLowerConfidenceInterval(conf1_index, r.MRTmean, r.MRTstdDev, r.N);
		r.confidence1MRTmax = getUpperConfidenceInterval(conf1_index, r.MRTmean, r.MRTstdDev, r.N);
		r.confidence2MRTmin = getLowerConfidenceInterval(conf2_index, r.MRTmean, r.MRTstdDev, r.N);
		r.confidence2MRTmax = getUpperConfidenceInterval(conf2_index, r.MRTmean, r.MRTstdDev, r.N);
		
		// ADDED TO SOLVE TASK1
		r.steps = r.N;
		r.measuredThroughput = new double[r.steps];
		for(int i=0; i<r.steps; i++) {
			r.measuredThroughput[i] = T[SKIP_MARGINS + i];
		}
		r.measuredResponseTime = new double[r.steps];
		for(int i=0; i<r.steps; i++) {
			r.measuredResponseTime[i] = ART[SKIP_MARGINS + i];
		}
		r.measuredThinkTime = new double[r.steps];
		for(int i=0; i<r.steps; i++) {
			r.measuredThinkTime[i] = ATT[SKIP_MARGINS + i];
		}
			
		// END ADDED ...
		
		// ADDED TO SOLVE TASK2
		System.out.println("Jobs arriving: " + average(task2Data.jA, SKIP_MARGINS, task2Data.jA.length - SKIP_MARGINS));
		System.out.println("Jobs completed: " + average(task2Data.jC, SKIP_MARGINS, task2Data.jC.length - SKIP_MARGINS));
		System.out.println("ARRIVAL RATE: " + ((double)average(task2Data.jA, SKIP_MARGINS, task2Data.jA.length - SKIP_MARGINS) * 1000.0 / (double)interpreter_step ));
		System.out.println("THROUGHPUT: " + r.Tmean);
		System.out.println("SYSTEM UTILIZATION: " + average(task2Data.utili, SKIP_MARGINS, task2Data.utili.length - SKIP_MARGINS));
		System.out.println("SERVICE TIME: " + average(task2Data.serviceTime, SKIP_MARGINS, task2Data.serviceTime.length - SKIP_MARGINS));
		System.out.println("ACTIVE JOBS IN SYSTEM: " + average(task2Data.averageActiveJobs, SKIP_MARGINS, task2Data.averageActiveJobs.length - SKIP_MARGINS));
		System.out.println("Busy time: " + average(task2Data.busies, SKIP_MARGINS, task2Data.busies.length - SKIP_MARGINS));
		System.out.println("Average time spent in system: " + average(task2Data.aSS, SKIP_MARGINS, task2Data.aSS.length - SKIP_MARGINS));
		
		
		System.out.println("SERVER THROUGHPUT 0: " + average(task2Data.server_throughput[0], SKIP_MARGINS, task2Data.server_throughput[0].length - SKIP_MARGINS));
		System.out.println("SERVER THROUGHPUT 1: " + average(task2Data.server_throughput[1], SKIP_MARGINS, task2Data.server_throughput[1].length - SKIP_MARGINS));
		System.out.println("SERVER THROUGHPUT 2: " + average(task2Data.server_throughput[2], SKIP_MARGINS, task2Data.server_throughput[2].length - SKIP_MARGINS));

		System.out.println("SERVER server_mean_service_rate 0: " + average(task2Data.server_mean_service_rate[0], SKIP_MARGINS, task2Data.server_mean_service_rate[0].length - SKIP_MARGINS));
		System.out.println("SERVER server_mean_service_rate 1: " + average(task2Data.server_mean_service_rate[1], SKIP_MARGINS, task2Data.server_mean_service_rate[1].length - SKIP_MARGINS));
		System.out.println("SERVER server_mean_service_rate 2: " + average(task2Data.server_mean_service_rate[2], SKIP_MARGINS, task2Data.server_mean_service_rate[2].length - SKIP_MARGINS));

		System.out.println("SERVER server_utilization 0: " + average(task2Data.server_utilization[0], SKIP_MARGINS, task2Data.server_utilization[0].length - SKIP_MARGINS));
		System.out.println("SERVER server_utilization 1: " + average(task2Data.server_utilization[1], SKIP_MARGINS, task2Data.server_utilization[1].length - SKIP_MARGINS));
		System.out.println("SERVER server_utilization 2: " + average(task2Data.server_utilization[2], SKIP_MARGINS, task2Data.server_utilization[2].length - SKIP_MARGINS));
		
		
//		task2Data.
		r.thinkTime = 0;
		for (int i = 0; i < r.measuredThinkTime.length ; i++) {
			r.thinkTime += r.measuredThinkTime[i];
		}		
		r.thinkTime = r.thinkTime / r.measuredThinkTime.length;
		r.utilizationPercentage = 0;
		for (int i = SKIP_MARGINS; i < task2Data.utili.length - SKIP_MARGINS; i++) {
			r.utilizationPercentage += task2Data.utili [i];
		}
		r.utilizationPercentage /= (double) (task2Data.utili.length - 2 * SKIP_MARGINS);
		r.serviceTime = 0;
		for (int i = SKIP_MARGINS; i < task2Data.serviceTime.length - SKIP_MARGINS; i++) {
			r.serviceTime += task2Data.serviceTime[i];
		}
		r.serviceTime /= (double) (task2Data.serviceTime.length - 2 * SKIP_MARGINS);
		r.averageJobNumber = 0;
		for (int i = SKIP_MARGINS; i < task2Data.averageActiveJobs.length - SKIP_MARGINS; i++) {
			r.averageJobNumber += task2Data.averageActiveJobs[i];
		}
		r.averageJobNumber /= (double) (task2Data.averageActiveJobs.length - 2 * SKIP_MARGINS);
		
		
		
//		r.busyTime = new double [r.steps];
//		for(int i=0; i<r.steps; i++) {
//			r.busyTime[i] = task2Data.busies[SKIP_MARGINS + i];
//		}
//		r.jobsArriving = new long [r.steps];
//		for(int i=0; i<r.steps; i++) {
//			r.jobsArriving[i] = task2Data.jA [SKIP_MARGINS + i];
//		}
//		r.jobsCompleted = new long [r.steps];
//		for(int i=0; i<r.steps; i++) {
//			r.jobsCompleted[i] = task2Data.jC[SKIP_MARGINS + i];
//		}
//		r.jobsRemaining = new long [r.steps];
//		for(int i=0; i<r.steps; i++) {
//			r.jobsRemaining[i] = task2Data.jR[SKIP_MARGINS + i];
//		}
//		r.averageTimeSpentInSystem = new double [r.steps];
//		for(int i=0; i<r.steps; i++) {
//			r.averageTimeSpentInSystem[i] = task2Data.aSS[SKIP_MARGINS + i];
//		}
		
		// END ADDED ...
		return r;
	}

	public static long average(long []a, int i, int j) {
		long result = 0;
		for (int k = i; k < j; k++) {
			result += a[k];
		}
		if (j > i) {
			result = result / (j - i);
		}
		return result;
	}
	public static double average(double []a, int i, int j) {
		double result = 0;
		for (int k = i; k < j; k++) {
			result += a[k];
		}
		if (j > i) {
			result = result / (j - i);
		}
		return result;
	}
	public static long average(long []a) {
		return average (a, 0, a.length);
	}
	
	public static String getGnuPlotForExperiment(String txtFileName, int []params) {
		String importantParts = txtFileName.replaceAll("\\.txt", "");
		String title = "";
		boolean is_first_in_title = true;
		for(int i=0; i<params.length; i++) {
			if(params[i] != 0) {
				if(!is_first_in_title) {
					title += ", ";
				} else {
					is_first_in_title = false;
				}
				title += RealResult.params_codes[i] + ": " + params[i];
			}
		}
return "\n"+
"# Gnuplot script file for generating 3 graphs for a measurement\n"+
"set autoscale\n"+
"unset log\n"+
"unset label\n"+
"set xtic auto\n"+
"set ytic auto\n"+
"set title \"Throughput - "+title+"\" font \"Calibri,15\"\n"+
"set xlabel \"Time (s)\"\n"+
"set ylabel \"Throughput (q/s)\"\n"+
"set yrange[0:]\n"+
"set terminal png\n"+
"set output \""+importantParts+"_Throughput.png\"\n"+
"set datafile separator \",\"\n"+
"set key off\n"+
"plot \""+txtFileName+"\" using 3:4 with linespoint pointtype 9\n"+
"\n"+
"set autoscale\n"+
"unset log\n"+
"unset label\n"+
"set xtic auto\n"+
"set ytic auto\n"+
"set title \"Response Times - "+title+"\" font \"Calibri,15\"\n"+
"set xlabel \"Time (s)\"\n"+
"set ylabel \"Response Time (ms)\"\n"+
"set yrange[0:]\n"+
"set terminal png\n"+
"set output \""+importantParts+"_RT.png\"\n"+
"set datafile separator \",\"\n"+
"set key bottom Left\n"+
"plot	\""+txtFileName+"\" using 3:6 title \"Median Response Time\" with linespoint pointtype 9,\\\n"+
"		\""+txtFileName+"\" using 3:5 title \"Average Response Time\" with linespoint pointtype 8\n"+
"\n";
	}

	
	private static double ComputeThroughput(ArrayList<ResponseMeasurement> results, long milliseconds) {
		double seconds = milliseconds / 1000.0;
		int successfull_queries = 0;
		for(ResponseMeasurement r : results) {
			if(r.getSuccess()) {
				successfull_queries ++;
			}
		}
		
		return ((double)successfull_queries)/seconds;
	}
	
	private static double ComputeMedianResponseTime(ArrayList<ResponseMeasurement> results) {
		long []ms = new long[results.size()];
		int i = 0;
		for(ResponseMeasurement r : results) {
			ms[i++] = r.getMilliseconds();
		}
		Arrays.sort(ms);
		if(ms.length % 2 == 1) {
			// Odd number
			int middle = (ms.length - 1) / 2;
			return ms[middle];
		} else {
			// Even number
			int middle1 = ms.length / 2 - 1;
			int middle2 = ms.length / 2 ;
			return ((double)(ms[middle1] + ms[middle2])) / 2;
		}
	}
	
	private static double ComputeMedianThinkTime(ArrayList<ThinkMeasurement> results) {
		long []ms = new long[results.size()];
		int i = 0;
		for(ThinkMeasurement r : results) {
			ms[i++] = r.getMilliseconds();
		}
		Arrays.sort(ms);
		if(ms.length % 2 == 1) {
			// Odd number
			int middle = (ms.length - 1) / 2;
			return ms[middle];
		} else {
			// Even number
			int middle1 = ms.length / 2 - 1;
			int middle2 = ms.length / 2 ;
			return ((double)(ms[middle1] + ms[middle2])) / 2;
		}
	}
	
	private static double ComputeAverageResponseTime(ArrayList<ResponseMeasurement> results) {
		long sum = 0;
		for(ResponseMeasurement r : results) {
			sum += r.getMilliseconds();
		}
		return ((double)sum) / results.size();
	}
	
	private static double ComputeAverageThinkTime(ArrayList<ThinkMeasurement> results) {
		long sum = 0;
		for(ThinkMeasurement r : results) {
			sum += r.getMilliseconds();
		}
		return ((double)sum) / results.size();
	}
	
	private static double ComputeMean(double []V, int skip_margins) {
		double mean = 0;
		for(int i=skip_margins; i<V.length-skip_margins; i++) {
			mean += V[i];
		}
		return mean / ((double)V.length - skip_margins - skip_margins);
	}
	
	private static double ComputeStdDev(double []V, double mean, int skip_margins) {
		double s = 0;
		for(int i=skip_margins; i<V.length-skip_margins; i++) {
			s += (V[i] - mean) * (V[i] - mean);
		}
		return Math.sqrt(s/((double)(V.length - 1 - skip_margins - skip_margins)));
	}

	private static double getLowerConfidenceInterval(int confidence_level, double mean, double stdDev, int N) {
		int index = N > 100 ? 101 : N;
		return mean - (criticalT[index][confidence_level] * stdDev) / Math.sqrt((double)N);
	}
	
	private static double getUpperConfidenceInterval(int confidence_level, double mean, double stdDev, int N) {
		int index = N > 100 ? 101 : N;
		return mean + (criticalT[index][confidence_level] * stdDev) / Math.sqrt((double)N);
	}

	private static double [][]criticalT = new double[][]  
   {
//    80%     90%     95%     98%     99%    99.8%
   	{0.000 , 0.000 , 0.000 , 0.000 , 0.000 , 0.000}, 
   	{3.078 , 6.314 ,12.706 ,31.821 ,63.657,318.313},
   	{1.886 , 2.920 , 4.303 , 6.965 , 9.925 ,22.327},
   	{1.638 , 2.353 , 3.182 , 4.541 , 5.841 ,10.215},
   	{1.533 , 2.132 , 2.776 , 3.747 , 4.604 , 7.173},
   	{1.476 , 2.015 , 2.571 , 3.365 , 4.032 , 5.893},
   	{1.440 , 1.943 , 2.447 , 3.143 , 3.707 , 5.208},
   	{1.415 , 1.895 , 2.365 , 2.998 , 3.499 , 4.782},
   	{1.397 , 1.860 , 2.306 , 2.896 , 3.355 , 4.499},
   	{1.383 , 1.833 , 2.262 , 2.821 , 3.250 , 4.296},
   	{1.372 , 1.812 , 2.228 , 2.764 , 3.169 , 4.143},
   	{1.363 , 1.796 , 2.201 , 2.718 , 3.106 , 4.024},
   	{1.356 , 1.782 , 2.179 , 2.681 , 3.055 , 3.929},
   	{1.350 , 1.771 , 2.160 , 2.650 , 3.012 , 3.852},
   	{1.345 , 1.761 , 2.145 , 2.624 , 2.977 , 3.787},
   	{1.341 , 1.753 , 2.131 , 2.602 , 2.947 , 3.733},
   	{1.337 , 1.746 , 2.120 , 2.583 , 2.921 , 3.686},
   	{1.333 , 1.740 , 2.110 , 2.567 , 2.898 , 3.646},
   	{1.330 , 1.734 , 2.101 , 2.552 , 2.878 , 3.610},
   	{1.328 , 1.729 , 2.093 , 2.539 , 2.861 , 3.579},
   	{1.325 , 1.725 , 2.086 , 2.528 , 2.845 , 3.552},
   	{1.323 , 1.721 , 2.080 , 2.518 , 2.831 , 3.527},
   	{1.321 , 1.717 , 2.074 , 2.508 , 2.819 , 3.505},
   	{1.319 , 1.714 , 2.069 , 2.500 , 2.807 , 3.485},
   	{1.318 , 1.711 , 2.064 , 2.492 , 2.797 , 3.467},
   	{1.316 , 1.708 , 2.060 , 2.485 , 2.787 , 3.450},
   	{1.315 , 1.706 , 2.056 , 2.479 , 2.779 , 3.435},
   	{1.314 , 1.703 , 2.052 , 2.473 , 2.771 , 3.421},
   	{1.313 , 1.701 , 2.048 , 2.467 , 2.763 , 3.408},
   	{1.311 , 1.699 , 2.045 , 2.462 , 2.756 , 3.396},
   	{1.310 , 1.697 , 2.042 , 2.457 , 2.750 , 3.385},
   	{1.309 , 1.696 , 2.040 , 2.453 , 2.744 , 3.375},
   	{1.309 , 1.694 , 2.037 , 2.449 , 2.738 , 3.365},
   	{1.308 , 1.692 , 2.035 , 2.445 , 2.733 , 3.356},
   	{1.307 , 1.691 , 2.032 , 2.441 , 2.728 , 3.348},
   	{1.306 , 1.690 , 2.030 , 2.438 , 2.724 , 3.340},
   	{1.306 , 1.688 , 2.028 , 2.434 , 2.719 , 3.333},
   	{1.305 , 1.687 , 2.026 , 2.431 , 2.715 , 3.326},
   	{1.304 , 1.686 , 2.024 , 2.429 , 2.712 , 3.319},
   	{1.304 , 1.685 , 2.023 , 2.426 , 2.708 , 3.313},
   	{1.303 , 1.684 , 2.021 , 2.423 , 2.704 , 3.307},
   	{1.303 , 1.683 , 2.020 , 2.421 , 2.701 , 3.301},
   	{1.302 , 1.682 , 2.018 , 2.418 , 2.698 , 3.296},
   	{1.302 , 1.681 , 2.017 , 2.416 , 2.695 , 3.291},
   	{1.301 , 1.680 , 2.015 , 2.414 , 2.692 , 3.286},
   	{1.301 , 1.679 , 2.014 , 2.412 , 2.690 , 3.281},
   	{1.300 , 1.679 , 2.013 , 2.410 , 2.687 , 3.277},
   	{1.300 , 1.678 , 2.012 , 2.408 , 2.685 , 3.273},
   	{1.299 , 1.677 , 2.011 , 2.407 , 2.682 , 3.269},
   	{1.299 , 1.677 , 2.010 , 2.405 , 2.680 , 3.265},
   	{1.299 , 1.676 , 2.009 , 2.403 , 2.678 , 3.261},
   	{1.298 , 1.675 , 2.008 , 2.402 , 2.676 , 3.258},
   	{1.298 , 1.675 , 2.007 , 2.400 , 2.674 , 3.255},
   	{1.298 , 1.674 , 2.006 , 2.399 , 2.672 , 3.251},
   	{1.297 , 1.674 , 2.005 , 2.397 , 2.670 , 3.248},
   	{1.297 , 1.673 , 2.004 , 2.396 , 2.668 , 3.245},
   	{1.297 , 1.673 , 2.003 , 2.395 , 2.667 , 3.242},
   	{1.297 , 1.672 , 2.002 , 2.394 , 2.665 , 3.239},
   	{1.296 , 1.672 , 2.002 , 2.392 , 2.663 , 3.237},
   	{1.296 , 1.671 , 2.001 , 2.391 , 2.662 , 3.234},
   	{1.296 , 1.671 , 2.000 , 2.390 , 2.660 , 3.232},
   	{1.296 , 1.670 , 2.000 , 2.389 , 2.659 , 3.229},
   	{1.295 , 1.670 , 1.999 , 2.388 , 2.657 , 3.227},
   	{1.295 , 1.669 , 1.998 , 2.387 , 2.656 , 3.225},
   	{1.295 , 1.669 , 1.998 , 2.386 , 2.655 , 3.223},
   	{1.295 , 1.669 , 1.997 , 2.385 , 2.654 , 3.220},
   	{1.295 , 1.668 , 1.997 , 2.384 , 2.652 , 3.218},
   	{1.294 , 1.668 , 1.996 , 2.383 , 2.651 , 3.216},
   	{1.294 , 1.668 , 1.995 , 2.382 , 2.650 , 3.214},
   	{1.294 , 1.667 , 1.995 , 2.382 , 2.649 , 3.213},
   	{1.294 , 1.667 , 1.994 , 2.381 , 2.648 , 3.211},
   	{1.294 , 1.667 , 1.994 , 2.380 , 2.647 , 3.209},
   	{1.293 , 1.666 , 1.993 , 2.379 , 2.646 , 3.207},
   	{1.293 , 1.666 , 1.993 , 2.379 , 2.645 , 3.206},
   	{1.293 , 1.666 , 1.993 , 2.378 , 2.644 , 3.204},
   	{1.293 , 1.665 , 1.992 , 2.377 , 2.643 , 3.202},
   	{1.293 , 1.665 , 1.992 , 2.376 , 2.642 , 3.201},
   	{1.293 , 1.665 , 1.991 , 2.376 , 2.641 , 3.199},
   	{1.292 , 1.665 , 1.991 , 2.375 , 2.640 , 3.198},
   	{1.292 , 1.664 , 1.990 , 2.374 , 2.640 , 3.197},
   	{1.292 , 1.664 , 1.990 , 2.374 , 2.639 , 3.195},
   	{1.292 , 1.664 , 1.990 , 2.373 , 2.638 , 3.194},
   	{1.292 , 1.664 , 1.989 , 2.373 , 2.637 , 3.193},
   	{1.292 , 1.663 , 1.989 , 2.372 , 2.636 , 3.191},
   	{1.292 , 1.663 , 1.989 , 2.372 , 2.636 , 3.190},
   	{1.292 , 1.663 , 1.988 , 2.371 , 2.635 , 3.189},
   	{1.291 , 1.663 , 1.988 , 2.370 , 2.634 , 3.188},
   	{1.291 , 1.663 , 1.988 , 2.370 , 2.634 , 3.187},
   	{1.291 , 1.662 , 1.987 , 2.369 , 2.633 , 3.185},
   	{1.291 , 1.662 , 1.987 , 2.369 , 2.632 , 3.184},
   	{1.291 , 1.662 , 1.987 , 2.368 , 2.632 , 3.183},
   	{1.291 , 1.662 , 1.986 , 2.368 , 2.631 , 3.182},
   	{1.291 , 1.662 , 1.986 , 2.368 , 2.630 , 3.181},
   	{1.291 , 1.661 , 1.986 , 2.367 , 2.630 , 3.180},
   	{1.291 , 1.661 , 1.986 , 2.367 , 2.629 , 3.179},
   	{1.291 , 1.661 , 1.985 , 2.366 , 2.629 , 3.178},
   	{1.290 , 1.661 , 1.985 , 2.366 , 2.628 , 3.177},
   	{1.290 , 1.661 , 1.985 , 2.365 , 2.627 , 3.176},
   	{1.290 , 1.661 , 1.984 , 2.365 , 2.627 , 3.175},
   	{1.290 , 1.660 , 1.984 , 2.365 , 2.626 , 3.175},
   	{1.290 , 1.660 , 1.984 , 2.364 , 2.626 , 3.174},
   	
   	{1.282 , 1.645 , 1.960 , 2.326 , 2.576 , 3.090}

   };

}
